//
// Created by QU on 2023/8/21.
//

#include <stdbool.h>
#include <stdlib.h>
#include <memory.h>

#include "CJFReborn.h"
#include "header.h"
#include "utils.h"
#include "paramPasser.h"
#include "dataGenerator.h"

bool VERBOSE_FLAG;
extern struct paramFlag paramFlag;

int main(int argc, char **argv) {
    VERBOSE_FLAG = false;

    struct strParameter strParam = parameterPasserToStrParam(argc, argv);
    struct numParameter numParam = parseStrParameterToNumParameter(paramFlag, strParam);
    if (VERBOSE_FLAG) { printInfoMessage("Parsing to numParam..."); }

#ifdef DEBUG_PRINT_PARAMETER_CONTENT
    printDebugMessage("Parameter Content:");
    printNumParameter(&numParam);
#endif

    if (paramFlag.structuremode == true) {
        if (multipleChannelGeneratorReborn(numParam)) {
            printInfoMessage("multipleChannelGeneratorReborn generate complete.");
        } else {
            printErrorMessage("multipleChannelGeneratorReborn generate ERROR.");
        }
    } else {
        if (singleChannelGeneratorReborn(numParam)) {
            printInfoMessage("singleChannelGenerator generate complete.");
        } else {
            printErrorMessage("singleChannelGenerator generate ERROR.");
        }
    }


    return 0;


}

bool singleChannelGeneratorReborn(struct numParameter numParam) {
    // 定义structureMode为9999时, 生成单通道.
    if (paramFlag.structuremode != false && numParam.numStructureMode != 9999) {
        printErrorMessage("Structure mode ERROR.");
        exit(EXIT_FAILURE);
    }

    if (numParam.numStartMFI >= 4096) {
        printWarningMessageWithExtraMessage("Internal", "MFI value out of range. Fix it with (%=MFI_MAX)");
    }

    if (paramFlag.structuremode == false) {
        printInfoMessageWithExtraMessage("singleChannelGenerator generating", "......");
    }

    //////////////////////////////////////////// 开辟空间
    // 需要生成的LOAD长度
//    size_t targetLoadLength = getBufferLengthFromGenFrameNum(numParam.numGenFrameNum, numParam.numVCType);

    // LoadLength * splitCols  一个逻辑通道(多个物理通道)下的 一帧Load的空间.
    size_t generateOneColLoadLength = getLoadLengthFromVCType(numParam.numVCType) * numParam.numSplitedCols;
    // 开辟生成连续数据的空间
    // | 00 01 02 03 | 04 05 06 07 | 08 09 10 11 | 12 13 14 15 |
    uint8_t *generateOneColLoadBuffer = malloc(generateOneColLoadLength);
    if (generateOneColLoadBuffer == NULL) {
        printErrorMessage("malloc buffer failed.");
        exit(EXIT_FAILURE);
    }

    // 除非你想要DEBUG, 一般不需要开启填充0.
    //    fillBlockWithZero(generateOneColLoadBuffer, generateOneColLoadLength);

    // 开辟的文件数据的缓存空间, 总和也是和上面的空间一样大, 这里存储的数据将会是按物理通道离散的.
    // 也就是说, 输出成文件的时候只需要输出对应的内存块即可.
    size_t outputFileOneColBufferLength = getLoadLengthFromVCType(numParam.numVCType) * numParam.numSplitedCols;
    // | 00 04 08 12 | 01 05 09 13 | 02 06 10 14 | 03 07 11 15 |
    // 必须开辟这部分空间, 因为每次写入一个字节不现实, 方便一次向文件中写入.
    uint8_t *outputFileOneColBuffer = malloc(outputFileOneColBufferLength);
    if (generateOneColLoadBuffer == NULL) {
        printErrorMessage("malloc buffer failed.");
        exit(EXIT_FAILURE);
    }
    //
    //    fillBlockWithZero(outputFileOneColBuffer, outputFileOneColBufferLength);
    if (VERBOSE_FLAG) { printInfoMessageWithExtraMessage("malloc generateBuffer and outputBuffer Success", ""); }

    ///////////////////////////////////////// 空间开辟完成
    // VC-n1-n2v
    // 第一步: 填充Header 每一个SplitCols只有一个Header. 循环中一次即可.
    char filename[50];
    uint16_t sq = 0;
    for (size_t currPhysicalID = numParam.numPhysicalID;
         currPhysicalID < numParam.numPhysicalID + numParam.numSplitedCols; ++currPhysicalID) {

        // 得到文件名称. 准备创建文件.
        sprintf(filename, "Data_PhysicalChannel_%zu.dat", currPhysicalID); // 生成文件名，例如：file1.txt, file2.txt, ...
        if (VERBOSE_FLAG) {
            printInfoMessageWithExtraMessage("Preparing FileHeaders", filename);
        }
        vcTypeHeader_t header = prepareHeadersData(numParam.numLogicalID, currPhysicalID, sq,
                                                   numParam.numGenFrameNum, numParam.numVCType);
        // 填充header, 创建文件.
        if (fillHeadersReborn(filename, header)) {
#ifdef DEBUG_PRINT_HEADER_CONTENT
            printDebugMessageWithExtraMessage("Header Content:", filename);
            printVCTypeHeader(&header);
#endif
            if (VERBOSE_FLAG) {
                printInfoMessage("Fill Headers complete.");
            }
        } else {
            printErrorMessage("FillHeaders ERROR");
            return false;
        }
        sq++;
    }
    if (VERBOSE_FLAG) { printInfoMessageWithExtraMessage("generate File Headers Complete", "\n"); }

    /////////////////////// MFI 和 LAOD 部分 /////////////////////////////////

    size_t continueIndex = 0;       // 这个作为填充到的位置的定位.
    uint16_t currMFI = numParam.numStartMFI %= MFI_MAX;

    // 每次填充一个 vcLOAD * splitCols长度, 每填充一次, 生成一次数据. 可以理解为列标.
    for (size_t currColFrame = 0; currColFrame < numParam.numGenFrameNum; ++currColFrame) {

        // 空间前面分配完了, 填充数据到原始数据块中.
        switch (numParam.numGenDataType) {
            case FIXED_60A1DA8E:
                generateData_60a1da8e(generateOneColLoadBuffer, generateOneColLoadLength, &continueIndex);
#ifdef DEBUG_PRINT_MALLOCBUFFER_CONTENT
                printDebugMessage("generateBuffer Content:");
                printf("current filling oneColsFrame num: %zu\n", currColFrame);
                printBufferDataContent(generateOneColLoadBuffer, generateOneColLoadLength);
#endif
                break;
            case FIXED_LowerINC_HigherLOID:
                generateData_LowerIncrementHigherLogicalID(generateOneColLoadBuffer, generateOneColLoadLength,
                                                           &continueIndex, numParam.numLogicalID);
#ifdef DEBUG_PRINT_MALLOCBUFFER_CONTENT
                printDebugMessage("generateBuffer Content:");
                printf("current filling oneColsFrame num: %zu\n", currColFrame);
                printBufferDataContent(generateOneColLoadBuffer, generateOneColLoadLength);
#endif
                break;
            case FIXED_LogicINC:
                generateData_ChannelIncrement(generateOneColLoadBuffer, generateOneColLoadLength, &continueIndex,
                                              numParam.numLogicalID);
#ifdef DEBUG_PRINT_MALLOCBUFFER_CONTENT
                printDebugMessage("generateBuffer Content:");
                printf("current filling oneColsFrame num: %zu\n", currColFrame);
                printBufferDataContent(generateOneColLoadBuffer, generateOneColLoadLength);
#endif
                break;
            case FIXED_00TOFF:
                generateData_00toFF(generateOneColLoadBuffer, generateOneColLoadLength, &continueIndex);
#ifdef DEBUG_PRINT_MALLOCBUFFER_CONTENT
                printDebugMessage("generateBuffer Content:");
                printf("current filling oneColsFrame num: %zu\n", currColFrame);
                printBufferDataContent(generateOneColLoadBuffer, generateOneColLoadLength);
#endif
                break;
            case INPUTFILE:
                break;
        }
        if (VERBOSE_FLAG) {
            printInfoMessage("fill data into generateBuffer complete");
        }

        // 数据向generateOneColBuffer填充完毕. 下一步开始数据间插

        // 数据间插开始. 间插到输出内存块中(outputFileOneColBuffer).
        int splitCols = 0;
        int outputBufferIndex = 0;
        for (size_t generateBufferIndex = 0; generateBufferIndex < generateOneColLoadLength; ++generateBufferIndex) {
            outputFileOneColBuffer[outputBufferIndex + (splitCols * getLoadLengthFromVCType(
                    numParam.numVCType))] = generateOneColLoadBuffer[generateBufferIndex];
            splitCols++;
            if (splitCols % numParam.numSplitedCols == 0) {
                splitCols %= numParam.numSplitedCols;
                outputBufferIndex++;
            }
        }

#ifdef DEBUG_PRINT_OUTPUTBUFFER_CONTENT
        printDebugMessage("outputBuffer Content:");
        printBufferDataContent(outputFileOneColBuffer, outputFileOneColBufferLength);
#endif
        if (VERBOSE_FLAG) {
            printInfoMessage("split mallocBlock to outputBuffer Complete");

        }
        // 数据间插到内存完成. 准备将MFI和间插后的数据填充到文件中.

        ///////////////////////////////////////////////////////////////////////////
        // MFI随着大帧填充一次而递增.
        if (VERBOSE_FLAG) {
            printInfoMessageWithExtraMessage("Filling MFI and LOAD part to File", "");
        }

        size_t nColsFrameIndex = 0;

        // 可以理解为行标.
        for (size_t currPhysicalID = numParam.numPhysicalID;
             currPhysicalID < numParam.numPhysicalID + numParam.numSplitedCols; ++currPhysicalID) {
            // 得到文件名.
            sprintf(filename, "Data_PhysicalChannel_%zu.dat", currPhysicalID); // 生成文件名，例如：file1.txt, file2.txt, ...
            if (VERBOSE_FLAG) {
                printInfoMessageWithExtraMessage("Filling DataFile:", filename);
            }

            // MFI
            if (fillMFIReborn(filename, currMFI)) {
                if (VERBOSE_FLAG) {
                    printInfoMessage("filling MFI Success.");
#ifdef DEBUG_PRINT_CURRENT_MFI_CONTENT
                    char printCurrMFIContent[20];
                    sprintf(printCurrMFIContent, "MFI value is: %d", currMFI);
                    printDebugMessage(printCurrMFIContent);
#endif
                }
            } else {
                printErrorMessage("filling MFI Failed.");
                exit(EXIT_FAILURE);
            }

            // LOAD
            // 前面的output的空间就是这个

            if (fillLoadReborn(filename, numParam.numVCType, outputFileOneColBuffer, outputFileOneColBufferLength,
                               nColsFrameIndex)) {
                if (VERBOSE_FLAG) {
                    printInfoMessage("filling LOAD Success.");
                }
            } else {
                printErrorMessage("filling LOAD Failed.");
                exit(EXIT_FAILURE);
            }

            nColsFrameIndex++;
        }

        // 对MFI的处理.
        currMFI++;
        currMFI %= MFI_MAX;

        if (VERBOSE_FLAG) {
            printf("\n");
        }
    }
    return true;
}

bool multipleChannelGeneratorReborn(struct numParameter numParam) {
    if (paramFlag.structuremode == false || numParam.numStructureMode == 9999) {
        printErrorMessage("Structure mode ERROR.");
    }

    printInfoMessage("multipleChannelGeneratorReborn generating...");

    struct numParameter tempParam = {0};

    switch (numParam.numStructureMode) {
// 0~255：全 VC-4 模式（10G SDH 中包含 64 个 VC-4）
//0:  全 VC-4 模式，每个 VC-4 为一个单独的逻辑通道
        case 0:
            tempParam.numStructureMode = 9999;
            tempParam.numSplitedCols = 1;
            tempParam.numVCType = VC_4;
            tempParam.numGenFrameNum = numParam.numGenFrameNum;
            tempParam.numPhysicalID = numParam.numPhysicalID;
            tempParam.numLogicalID = numParam.numLogicalID;
            tempParam.numStartMFI = numParam.numStartMFI;
            tempParam.numGenDataType = numParam.numGenDataType;

            if (VERBOSE_FLAG) {
                printDebugMessage("tempNumParamStarter Content:");
                printNumParameter(&tempParam);
            }


            for (int i = 0; i < 64; ++i) {
                if (singleChannelGeneratorReborn(tempParam)) {
                    tempParam.numLogicalID++;
                    tempParam.numPhysicalID++;
                } else {
                    printErrorMessageWithExtraMessage("singleChannelGenerator ERROR.", "Aborting...");
                    return false;
                }
            }

            break;

//1：全 VC-4 模式，64 个 VC-4 组合成 1 个逻辑通道
        case 1:
            // -S 1 --gentype 00toff --genframenum 640 --startphysicalid 0 --startlogicalid 0 --startmfi 100
            tempParam.numStructureMode = 9999;
            tempParam.numSplitedCols = 64;
            tempParam.numVCType = VC_4;
            tempParam.numGenFrameNum = numParam.numGenFrameNum;
            tempParam.numPhysicalID = numParam.numPhysicalID;
            tempParam.numLogicalID = numParam.numLogicalID;
            tempParam.numStartMFI = numParam.numStartMFI;
            tempParam.numGenDataType = numParam.numGenDataType;

            if (VERBOSE_FLAG) {
                printDebugMessage("tempNumParamStarter Content:");
                printNumParameter(&tempParam);
            }

            if (singleChannelGeneratorReborn(tempParam)) {
            } else {
                printErrorMessageWithExtraMessage("singleChannelGenerator ERROR.", "Aborting...");
                return false;
            }
            break;
//2：全 VC-4 模式，32 个 VC-4 组合成 1 个逻辑通道，其它每个 VC-4 为独立的逻辑通道
        case 2:
            //  -S 2 --gentype 00toff --genframenum 320 --startphysicalid 0 --startlogicalid 0 --startmfi 100
            // 32个逻辑1
            tempParam.numStructureMode = 9999;
            tempParam.numSplitedCols = 32;
            tempParam.numVCType = VC_4;
            tempParam.numGenFrameNum = numParam.numGenFrameNum;
            tempParam.numPhysicalID = numParam.numPhysicalID;
            tempParam.numLogicalID = numParam.numLogicalID;
            tempParam.numStartMFI = numParam.numStartMFI;
            tempParam.numGenDataType = numParam.numGenDataType;

            if (VERBOSE_FLAG) {
                printDebugMessage("tempNumParamStarter Content:");
                printNumParameter(&tempParam);
            }

            if (singleChannelGeneratorReborn(tempParam)) {
            } else {
                printErrorMessageWithExtraMessage("singleChannelGenerator ERROR.", "Aborting...");
                return false;
            }

            tempParam.numPhysicalID += 32;
            tempParam.numLogicalID++;

            tempParam.numStructureMode = 9999;
            tempParam.numSplitedCols = 1;
            tempParam.numVCType = VC_4;
            tempParam.numGenFrameNum = numParam.numGenFrameNum;
            tempParam.numStartMFI = numParam.numStartMFI;
            tempParam.numGenDataType = numParam.numGenDataType;

            for (int i = 0; i < 32; ++i) {
                if (singleChannelGeneratorReborn(tempParam)) {
                } else {
                    printErrorMessageWithExtraMessage("singleChannelGenerator ERROR.", "Aborting...");
                    return false;
                }
                tempParam.numLogicalID++;
                tempParam.numPhysicalID++;
            }

            break;



//256~511：全 VC-12 模式（10G SDH 中包含 4032 个 VC-4）
//256:  全 VC-12 模式，每个 VC-12 为一个单独的逻辑通道
        case 256:
            //  -S 256 --gentype 00toff --genframenum 30 --startphysicalid 0 --startlogicalid 0 --startmfi 100  > mode256_output.txt
            tempParam.numStructureMode = 9999;
            tempParam.numSplitedCols = 1;
            tempParam.numVCType = VC_12;
            tempParam.numGenFrameNum = numParam.numGenFrameNum;
            tempParam.numPhysicalID = numParam.numPhysicalID;
            tempParam.numLogicalID = numParam.numLogicalID;
            tempParam.numStartMFI = numParam.numStartMFI;
            tempParam.numGenDataType = numParam.numGenDataType;
            if (VERBOSE_FLAG) {
                printDebugMessage("tempNumParamStarter Content:");
                printNumParameter(&tempParam);
            }

            for (int i = 0; i < 4032; ++i) {
                if (singleChannelGeneratorReborn(tempParam)) {
                } else {
                    printErrorMessageWithExtraMessage("singleChannelGenerator ERROR.", "Aborting...");
                    return false;
                }
                tempParam.numLogicalID++;
                tempParam.numPhysicalID++;
            }


            break;
//257：全 VC-12 模式，每 64 个 VC-12 组合成 1 个逻辑通道（需注意 VC-12-Xv， X 的值最大为 64），共 63 个逻辑通道。
        case 257:
            //  -S 257 --gentype 00toff --genframenum 640 --startphysicalid 0 --startlogicalid 0 --startmfi 100  > mode257_output.txt
            tempParam.numStructureMode = 9999;
            tempParam.numSplitedCols = 64;
            tempParam.numVCType = VC_12;
            tempParam.numGenFrameNum = numParam.numGenFrameNum;
            tempParam.numPhysicalID = numParam.numPhysicalID;
            tempParam.numLogicalID = numParam.numLogicalID;
            tempParam.numStartMFI = numParam.numStartMFI;
            tempParam.numGenDataType = numParam.numGenDataType;
            if (VERBOSE_FLAG) {
                printDebugMessage("tempNumParamStarter Content:");
                printNumParameter(&tempParam);
            }

            for (int i = 0; i < 63; ++i) {
                if (singleChannelGeneratorReborn(tempParam)) {
                } else {
                    printErrorMessageWithExtraMessage("singleChannelGenerator ERROR.", "Aborting...");
                    return false;
                }
                tempParam.numPhysicalID += 64;
                tempParam.numLogicalID++;
            }


            break;
//512~767：VC-4/VC-12 混合模式
//512：63 个 VC-4，63 个 VC-12；63 个 VC-4 组成 1 个逻辑通道，63 个 VC-12 组成 1 个逻辑通道。
        case 512:
            // --structuremode 512 --gentype 00toff --genframenum 126 --startphysicalid 0 --startlogicalid 0 --startmfi 100

            tempParam.numStructureMode = 9999;
            tempParam.numSplitedCols = 63;
            tempParam.numVCType = VC_4;
            tempParam.numGenFrameNum = numParam.numGenFrameNum;
            tempParam.numPhysicalID = numParam.numPhysicalID;
            tempParam.numLogicalID = numParam.numLogicalID;
            tempParam.numStartMFI = numParam.numStartMFI;
            tempParam.numGenDataType = numParam.numGenDataType;
            if (VERBOSE_FLAG) {
                printDebugMessage("tempNumParamStarter Content:");
                printNumParameter(&tempParam);
            }

            if (singleChannelGeneratorReborn(tempParam)) {
            } else {
                printErrorMessageWithExtraMessage("singleChannelGenerator ERROR.", "Aborting...");
                return false;
            }

            tempParam.numPhysicalID += 63;
            tempParam.numLogicalID++;

            ////////
            tempParam.numSplitedCols = 63;
            tempParam.numVCType = VC_12;
            if (VERBOSE_FLAG) {
                printDebugMessage("tempNumParamStarter Content:");
                printNumParameter(&tempParam);
            }
            if (singleChannelGeneratorReborn(tempParam)) {
            } else {
                printErrorMessageWithExtraMessage("singleChannelGenerator ERROR.", "Aborting...");
                return false;
            }


            break;

//我们暂时只以上产生 6 种通道结构，并用 STRUCTURE_MODE 参数为 0、1、2、 256、257、512 分别表示这 6 种结构。

        default:
            printf("Unknown STRUCTURE_MODE value...\n");
            exit(EXIT_FAILURE);
    }

    return true;
}


vcTypeHeader_t
prepareHeadersData(uint16_t logicalChannelID, uint16_t physicalChannelID, uint16_t SQ,
                   uint16_t frameNum, uint16_t vc_type) {
    vcTypeHeader_t result;

    result.logicalChannelID = logicalChannelID;
    result.physicalChannelID = physicalChannelID;
    result.SQ = SQ;
    result.frameNum = frameNum;
    result.vc_type = vc_type;

    switch (vc_type) {
        case VC_4:
            result.frameLength = VC4_FRAME_BODY_LENGTH;
            break;
        case VC_12:
            result.frameLength = VC12_FRAME_BODY_LENGTH;
            break;
        default:
            printErrorMessage("Unknown VC type");
            exit(EXIT_FAILURE);
    }

    return result;
}


bool fillHeadersReborn(char *filename, vcTypeHeader_t header) {
    FILE *currFile;
    currFile = fopen(filename, "wb");
    if (currFile == NULL) {
        printErrorMessageWithExtraMessage("Can't open file: ", filename);
        exit(EXIT_FAILURE);
    }

    // 向文件中填充header
    fwrite(&header, sizeof(vcTypeHeader_t), 1, currFile);

    fclose(currFile);
    return true;
}


bool fillMFIReborn(char *filename, uint16_t MFI) {
    FILE *currFile;
    currFile = fopen(filename, "ab");
    if (currFile == NULL) {
        printErrorMessageWithExtraMessage("Can't open file: ", filename);
        exit(EXIT_FAILURE);
    }

    // 向文件中填充MFI
    fwrite(&MFI, sizeof(uint16_t), 1, currFile);

    fclose(currFile);
    return true;
}

bool fillLoadReborn(char *filename, enum VC_TYPE vcType, uint8_t *outputOneColBuffer, size_t outputOneColBufferLength,
                    size_t nColsFrame) {
    FILE *currFile;
    currFile = fopen(filename, "ab");
    if (currFile == NULL) {
        printErrorMessageWithExtraMessage("Can't open file: ", filename);
        exit(EXIT_FAILURE);
    }

    size_t vcBufferLength;
    switch (vcType) {
        case VC_4:
            vcBufferLength = VC4_FRAME_LOAD_LENGTH;
            break;
        case VC_12:
            vcBufferLength = VC12_FRAME_LOAD_LENGTH;
            break;
        default:
            printErrorMessage("Unknown VC type");
            exit(EXIT_FAILURE);
    }

    if ((nColsFrame + 1) * vcBufferLength > outputOneColBufferLength) {
        printErrorMessage("FillLoad nColsFrame not Correct.");
        return false;
    }

    // 写入LOAD数据
    fwrite(outputOneColBuffer + (nColsFrame * vcBufferLength), vcBufferLength, 1, currFile);

    fclose(currFile);
    return true;

}


